/*
 * Copyright (c) 2018. 玺得（深圳）科技有限公司.保留所有权利. http://www.pi-top.com/ 玺得（深圳）科技有限公司保留所有代码著作权.如有任何疑问请访问官方网站与我们联系. 代码只针对特定需求定制编码，不得在未经允许或授权的情况下对外传播扩散.恶意传播者，法律后果自行承担. 本代码仅用于pps-cloud系统.
 */
package com.pitop.base.ctrl;


import com.opensso.sdk.client.SSOClient;
import com.opensso.sdk.client.SessionEnum;
import com.opensso.sdk.security.JwtToken;
import com.opensso.sdk.tools.SessionTools;
import com.pitop.core.entity.BeanRet;
import com.pitop.core.exceptions.BaseException;
import com.pitop.core.tools.redis.RedisUtils;
import com.pitop.setting.entity.Setting;
import com.pitop.setting.service.SettingSVImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * 账户 控制器
 *
 * @author pi-top
 */
@RestController
@RequestMapping("/login")
@Slf4j
@Api(value = "账户控制器", description = "账户控制器")
public class TokenCtrl {

    @Resource
    protected RedisUtils redisUtils;

    @Resource
    private SettingSVImpl settingSVImpl;//设置

    /**
     * 注销用户
     *
     * @return BeanRet
     */
    @ApiOperation(value = "注销用户", notes = "注销用户")
    @GetMapping(value = "/signout")
    @ResponseBody
    public BeanRet signout(HttpServletRequest request) {
        String token = request.getHeader(SessionEnum.Authorization.name());
        String sso_apikey = settingSVImpl.loadByK(Setting.Key.SSO_ApiKey.name()).getV();
        String sso_host = settingSVImpl.loadByK(Setting.Key.SSO_HOST.name()).getV();

        SSOClient.Instance
                .apikey(sso_apikey)
                .token(token)
                .host(sso_host)
                .invalidate();

        return BeanRet.create(false, BaseException.BaseExceptionEnum.Session_Error);
    }

    /**
     * 注销局部session
     * 1.获取token
     * 2.拿出token中注销的指令以及sessionkey准备注销
     * 3.拿出本地token进行注销
     * 4.返回注销成功
     *
     * @return BeanRet
     */
    @ApiOperation(value = "SSO回调方法", notes = "SSO回调方法")
    @PostMapping(value = "/invalidate")
    @ResponseBody
    public BeanRet invalidate(HttpServletRequest request) {
        //1.获取token
        String token = request.getHeader(SessionEnum.Authorization.name());
        if (StringUtils.isBlank(token)) {
            return BeanRet.create();
        }
        String sso_apisecret = settingSVImpl.loadByK(Setting.Key.SSO_ApiSecret.name()).getV();
        boolean isVerifier = JwtToken.verifier(token, sso_apisecret);
        if (!isVerifier) {
            return BeanRet.create(false, BaseException.BaseExceptionEnum.Session_Error);
        }

        //2.拿出token中注销的指令以及sessionkey准备注销
        String invalidateCammand = JwtToken.getTokenValue(token, sso_apisecret, SessionEnum.Invalidate.name());
        String sessionKey = SessionTools.Instance.genSessionKey(invalidateCammand);
        //3.拿出本地token进行注销
        redisUtils.del(sessionKey);

        //4.返回注销成功
        return BeanRet.create(true, BaseException.BaseExceptionEnum.Success);
    }


    /**
     * 刷新token
     *
     * @return BeanRet
     */
    @ApiOperation(value = "刷新token", notes = "刷新token")
    @GetMapping(value = "/refresh")
    @ResponseBody
    public BeanRet refresh(HttpServletResponse response, HttpServletRequest request) {
        //1.获取token
        String refresh_Token = request.getHeader(SessionEnum.RefreshToken.name());
        String sso_host = settingSVImpl.loadByK(Setting.Key.SSO_HOST.name()).getV();
        log.info("刷新token >> sso_host:" + sso_host);
        String sso_apikey = settingSVImpl.loadByK(Setting.Key.SSO_ApiKey.name()).getV();
        log.info("刷新token >> sso_apikey:" + sso_apikey);

        String authorizationToken = SSOClient.Instance
                .host(sso_host)
                .token(refresh_Token)
                .refreshToken(sso_apikey);

        //4.返回注销成功
        response.addHeader(SessionEnum.Token.name(), authorizationToken);
        return BeanRet.create(true, BaseException.BaseExceptionEnum.Success, (Object) authorizationToken);
    }

}
